import threading
import time
import json
import os
import ctypes
from PIL import Image
from pystray import Icon as pystray_icon, Menu as pystray_menu, MenuItem as pystray_menu_item

# 从我们自己的模块中导入配置和功能
import config
import core_functions as core

os.system("chcp 65001 && cls")  # for Nuitka, GBK


class WallpaperApp:
    def __init__(self):
        # 初始化状态变量
        self.stop_event = threading.Event()
        self.update_lock = threading.Lock()
        self.is_startup_on = False
        self.current_source_name = ""
        self.current_source_object = None
        self.icon = None
        self.need_resize = True

        # --- 关键修改：确保程序在 AppData 中的数据目录存在 ---
        if not os.path.exists(config.APP_DATA_DIR):
            os.makedirs(config.APP_DATA_DIR)
            print('创建文件夹：', config.APP_DATA_DIR)
        # --- 修改结束 ---

        # 加载配置
        self._load_app_config()

        # 使用工厂函数创建URL生成器
        # 支持从 config.SOURCES 加载（优先），格式支持 dict 或 list（见示例）
        self.SOURCES = {}
        sources_cfg = getattr(config, 'SOURCES', None)
        if sources_cfg:
            # dict 形式：{ "菜单名": template_or_dict_or_callable, ... }
            if isinstance(sources_cfg, dict):
                for menu_name, spec in sources_cfg.items():
                    if callable(spec):
                        self.SOURCES[menu_name] = spec
                    elif isinstance(spec, dict):
                        tpl = spec.get('template') or spec.get('url')
                        delay = spec.get('delay', config.SATELLITE_IMAGE_DELAY_MINUTES)
                        if tpl:
                            self.SOURCES[menu_name] = core.create_satellite_url_generator(tpl, delay)
                    elif isinstance(spec, str):
                        self.SOURCES[menu_name] = core.create_satellite_url_generator(spec,
                                                                                      config.SATELLITE_IMAGE_DELAY_MINUTES)
            # list 形式：[{ "menu_name": "...", "template": "...", "delay": ... }, ...]
            elif isinstance(sources_cfg, list):
                for entry in sources_cfg:
                    if not isinstance(entry, dict):
                        continue
                    menu = entry.get('menu_name') or entry.get('name')
                    tpl = entry.get('template') or entry.get('url')
                    delay = entry.get('delay', config.SATELLITE_IMAGE_DELAY_MINUTES)
                    if menu and tpl:
                        self.SOURCES[menu] = core.create_satellite_url_generator(tpl, delay)
        # 回退到原来的两个默认源（兼容旧 config.py）
        if not self.SOURCES:
            generate_GCLR = core.create_satellite_url_generator(config.FY4B_GCLR_TEMPLATE,
                                                                config.SATELLITE_IMAGE_DELAY_MINUTES)
            generate_SWCI = core.create_satellite_url_generator(config.FY4B_SWCI_TEMPLATE,
                                                                config.SATELLITE_IMAGE_DELAY_MINUTES)
            self.SOURCES = {
                "风云4B真彩": generate_GCLR,
                "风云4B风暴": generate_SWCI,
            }

        # 设置初始源
        if self.current_source_name not in self.SOURCES:
            self.current_source_name = list(self.SOURCES.keys())[0]
        self.current_source_object = self.SOURCES[self.current_source_name]

    # --- 关键修改：从 AppData 路径加载和保存配置 ---
    def _load_app_config(self):
        try:
            # 直接使用 config.py 中定义好的完整路径
            with open(config.CONFIG_FILENAME, 'r') as f:
                app_config = json.load(f)
            self.is_startup_on = app_config.get('startup', False)
            self.need_resize = app_config.get('need_resize', True)
            self.current_source_name = app_config.get('source', '')
        except (FileNotFoundError, json.JSONDecodeError):
            print("未找到配置文件或格式错误，使用默认设置。")

    def _save_app_config(self):
        app_config = {'startup': self.is_startup_on, 'need_resize': self.need_resize, 'source': self.current_source_name}
        # 直接使用 config.py 中定义好的完整路径
        with open(config.CONFIG_FILENAME, 'w') as f:
            json.dump(app_config, f, indent=4)

    # --- 修改结束 ---

    # --- 后续所有代码均与您提供的版本相同，无需改动 ---
    def update_wallpaper_job(self):
        with self.update_lock:
            print(f"\n--- {time.ctime()} ---")
            width, height = core.get_screen_resolution()

            if callable(self.current_source_object):
                final_url = self.current_source_object()
            else:  # 保留对静态URL模板的支持
                final_url = self.current_source_object.format(width=width, height=height)

            download_path = os.path.join(config.SAVE_DIR, config.DOWNLOADED_FILE_NAME)
            processed_path = os.path.join(config.SAVE_DIR, config.PROCESSED_FILE_NAME)

            print(f"开始更新壁纸 (源: {self.current_source_name})")
            if final_url and core.download_image(final_url, download_path):
                if core.process_image(download_path, processed_path, width, height, self.current_source_name, self.need_resize):
                    core.set_wallpaper(processed_path)
                    print("壁纸更新成功。")
            else:
                print("壁纸更新失败。")

    def wallpaper_update_loop(self):
        self.update_wallpaper_job()
        while not self.stop_event.wait(config.UPDATE_INTERVAL_SECONDS):
            self.update_wallpaper_job()

    def on_source_selected(self, icon, item):
        self.current_source_name = item.text
        self.current_source_object = self.SOURCES[self.current_source_name]
        self._save_app_config()
        print(f"用户切换源到: {self.current_source_name}")
        self.on_update_clicked(icon, item)

    def on_startup_clicked(self, icon, item):
        self.is_startup_on = not self.is_startup_on
        core.manage_startup(self.is_startup_on)
        self._save_app_config()

    def on_resize_clicked(self, icon, item):
        self.need_resize = not self.need_resize
        self._save_app_config()
        self.on_update_clicked(icon, item)

    def on_update_clicked(self, icon, item):
        threading.Thread(target=self.update_wallpaper_job).start()

    def on_exit_clicked(self, icon, item):
        self.stop_event.set()
        self.icon.stop()

    def run(self):
        try:
            ctypes.windll.shcore.SetProcessDpiAwareness(2)
        except Exception:
            try:
                ctypes.windll.user32.SetProcessDPIAware()
            except Exception:
                pass

        icon_path = core.resource_path(config.ICON_FILENAME)
        try:
            image = Image.open(icon_path)
        except FileNotFoundError:
            print(f"错误: 找不到图标文件 '{config.ICON_FILENAME}'")
            return

        source_menu_items = [pystray_menu_item(
            name, self.on_source_selected,
            checked=lambda item, name=name: self.current_source_name == name, radio=True
        ) for name in self.SOURCES.keys()]

        menu = pystray_menu(
            *source_menu_items,
            pystray_menu.SEPARATOR,
            pystray_menu_item('开机时启动', self.on_startup_clicked, checked=lambda item: self.is_startup_on),
            pystray_menu_item('立即更新', self.on_update_clicked),
            pystray_menu_item('自适应壁纸', self.on_resize_clicked, checked=lambda item: self.need_resize),
            pystray_menu_item('退出', self.on_exit_clicked)
        )

        self.icon = pystray_icon("AutoWallpaper", image, "自动壁纸更换", menu)

        update_thread = threading.Thread(target=self.wallpaper_update_loop)
        update_thread.daemon = True
        update_thread.start()

        self.icon.run()
